Spring Boot自動配置原理,實戰

Java

Posted by Java on 2019-11-15 14:21:00

Spring Boot自動配置原理

Spring Boot的自動配置註解是@EnableAutoConfiguration, 從上面的@Import的類可以找到下面的自動加載自動配置的映射。


 
  1. org.springframework.core.io.support.SpringFactoriesLoader.loadFactoryNames(Class, ClassLoader)


 
  1. public static List loadFactoryNames(Class factoryClass, ClassLoader classLoader) {

  2.    String factoryClassName = factoryClass.getName();

  3.    try {

  4.        Enumeration urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :

  5.                lassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));

  6.        List result = new ArrayList();

  7.        while (urls.hasMoreElements()) {

  8.            URL url = urls.nextElement();

  9.            Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));

  10.            String factoryClassNames = properties.getProperty(factoryClassName);

  11.            result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));

  12.        }

  13.        return result;

  14.    }

  15.    catch (IOException ex) {

  16.        throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +

  17.                "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);

  18.    }

  19. }

這個方法會加載類路徑及所有jar包下META-INF / spring.factories配置中映射的自動配置的類。


 
  1. /**

  2. * The location to look for factories.

  3. *

    Can be present in multiple JAR files.

  4. */

  5. public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

查看Spring Boot自帶的自動配置的包: spring-boot-autoconfigure-1.5.6.RELEASE.jar,打開其中的META-INF / spring.factories文件會找到自動配置的映射。


 
  1. # Auto Configure

  2. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\

  3. org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\

  4. org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\

  5. org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\

  6. org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\

  7. org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\

  8. org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\

  9. org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\

  10. ...

再來看看數據源自動配置的實現註解


 
  1. @Configuration

  2. @ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })

  3. @EnableConfigurationProperties(DataSourceProperties.class)

  4. @Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })

  5. public class DataSourceAutoConfiguration {

  6. ...

@ Configuration,@ ConditionalOnClass即自動配置的核心,首先它得是一個配置文件,其次根據類路徑下是否有這個類去自動配置。

自動配置實戰

所以,了解了自動配置的原理,來自己實現一個自動配置的玩意其實很簡單。

添加配置類:


 

 

 

 

 

 

 

 

 

 

  1. import org.slf4j.Logger;

  2. import org.springframework.context.EnvironmentAware;

  3. import org.springframework.core.env.Environment;

  4. import com.oceanpayment.common.utils.logger.LoggerUtils;

  5. public class EnvConfig implements EnvironmentAware {

  6.    private final Logger logger = LoggerUtils.getLogger(this);

  7.    private Environment env;

  8.    public String getStringValue(String key) {

  9.        return env.getProperty(key);

  10.    }

  11.    public Long getLongValue(String key) {

  12.        String value = getStringValue(key);

  13.        try {

  14.            return Long.parseLong(value);

  15.        } catch (Exception e) {

  16.            logger.error("字符串转换Long失败:{} = {}", key, value);

  17.        }

  18.        return 0L;

  19.    }

  20.    public int getIntValue(String key) {

  21.        return getLongValue(key).intValue();

  22.    }

  23.    @Override

  24.    public void setEnvironment(Environment environment) {

  25.        this.env = environment;

  26.    }

  27. }

添加自動配置類:


 

 

 

 

  1. import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

  2. import org.springframework.context.annotation.Bean;

  3. import org.springframework.context.annotation.Configuration;

  4. import org.springframework.core.env.PropertyResolver;

  5. @Configuration

  6. @ConditionalOnClass(PropertyResolver.class)

  7. public class EnvAutoConfig {

  8.    @Bean

  9.    public EnvConfig envConfig() {

  10.        return new EnvConfig();

  11.    }

  12. }

創建META-INF / spring.factories文件,添加自動配置映射:


 
  1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\

  2. com.oceanpayment.common.config.env.EnvAutoConfig

這樣就搞定了。

查看自動配置報告

怎麼看自己加的自動配置類有沒有被加載,或者查看所有自動配置激活的和未激活的可以通過以下幾次試查看。

  1. spring-boot:在運行環境中加入debug = true變量 

  2. java -jar xx.jar —debug

  3. main方法運行,在VM Argumanets中加入-Ddebug

  4. 直接在應用程序文件中加入debug = true

  5. 如果集成了spring-boot-starter-actuator監控,則通過autoconfig端點也可以查看。

啟動後會在控制台看到以下自動配置報告信息:


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  1. =========================

  2. AUTO-CONFIGURATION REPORT

  3. =========================

  4. Positive matches:

  5. -----------------

  6.   AopAutoConfiguration matched:

  7.      - @ConditionalOnClass found required classes 'org.springframework.context.annotation.EnableAspectJAutoProxy', 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

  8.      - @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)

  9.   ...

  10.   EnvAutoConfig matched:

  11.      - @ConditionalOnClass found required class 'org.springframework.core.env.PropertyResolver'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

  12.   ErrorMvcAutoConfiguration matched:

  13.      - @ConditionalOnClass found required classes 'javax.servlet.Servlet', 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

  14.      - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)

  15.   ErrorMvcAutoConfiguration#basicErrorController matched:

  16.      - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.ErrorController; SearchStrategy: current) did not find any beans (OnBeanCondition)

  17.   ...

  18. Negative matches:

  19. -----------------

  20.   ActiveMQAutoConfiguration:

  21.      Did not match:

  22.         - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)

  23.   AopAutoConfiguration.JdkDynamicAutoProxyConfiguration:

  24.      Did not match:

  25.         - @ConditionalOnProperty (spring.aop.proxy-target-class=false) found different value in property 'proxy-target-class' (OnPropertyCondition)

  26.   ArtemisAutoConfiguration:

  27.      Did not match:

  28.         - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory' (OnClassCondition)

  29.   BatchAutoConfiguration:

  30.      Did not match:

  31.         - @ConditionalOnClass did not find required class 'org.springframework.batch.core.launch.JobLauncher' (OnClassCondition)

  32.   ...

正面匹配:已經啟用的自動配置

否定匹配項:未啟用的自動配置

從報告中看到自己添加的EnvAutoConfig已經自動配置了。